/**
* 	Flow v1.0 (Optimized gallery for large image previews)
* 
*	@author: 	Angel Kostadinov
* 	@copyright: 2011, Creozon
*/
(function($)
{	
	/* Flow class */
	var Flow  = 
	{
		ui: null,
		flow: null,
		images:[],
		options:
		{
			distance: 100,
			easing:  'linear',
			defaultSize:
			{
				width: 420,
				height:200
			},
			timeout: 300,
			blockUI:
			{
				speed: 		300,
				opacity: 	.85,
				zIndex: 	9998,
				background: 'rgb(0,0,0)'
			},
			resize: 
			{
				speed: 400,
				optimize: 100
			},
			image: 
			{
				fade: 300,
				draggable: true
			}
		},
		slide: 
		{
			next: 	 0,
			prev: 	 0,
			current: 0
		},
		getFlow: function()
		{
			var options = this.options;
			
			var F = Core.inherit(function()
			{
				options = $.extend(
				{
					offset:	2,
					resize:
					{
						speed: 300
					},
					easing: null
				}, options);
				
				return {
					isUIBlocked: false,
					size: 
					{
						width:0,
						height:0
					},
					timer: 
					{
						scroll: null,
						resize: null
					},
					element: null,
					resize: function(width, height, callback)
					{
						/* Make fine adjustment */
						width += 2 * options.offset;
						
						if (!this.size.width && !this.size.height) /* Store original size */
						{
							this.size.width  = width;
							this.size.height = height;
						}
						
						var currentSize = 
						{
							width:  this.element.width(),
							height: this.element.find('.mid > div > div')
						}
						
						/* Optimize animation speed if low difference of size */
						var speed = 50 > Math.abs(currentSize.width - width) ? options.resize.optimize : options.resize.speed;
						
						/* Resize box */
						this.element.animate(
						{
							width:		 width, 
							marginLeft:	-width/2,
							marginTop:	-height/2 + $(window).scrollTop()
						},speed, options.easing).find('.mid > div > div').animate(
						{
							height: height
						},speed, options.easing, Core.delegate(this, callback));
						
		
						$(window).unbind('scroll').bind(
						{
							scroll: Core.delegate(this, this.updateScroll)
						})
						
						return this;
					},
					reposition: function(top, left, callback)
					{
						this.element.stop().animate(
						{
							top:  top,
							left: left
						}, 0, options.easing, Core.delegate(this, callback));
					},
					content: function()
					{
						return this.element.find('.mid > div > div');
					},
					setContent:function(image)
					{
						this.empty();
						
						var append = function(index, element)
						{
							this.content().append(element);
							
							
						}

						var i = $(image).attr(
						{
							title: 'drag with mouse'
						}).hide(), wrapper = $('<div/>').css(
						{
							width:  this.size.width,
							height: this.size.height
						}).append(i);
						
						$.each(
						[
							wrapper
						], this.delegate(this, append));
						
						
						
												
						/* Resize image */
						var dim = 
						{
							width: 	i.width(),
							height: i.height(),
							ratio: 1
						}, property = null, value = null;
						
						/* Calculate ratio */
						dim.ratio = dim.width/dim.height;
						
						if (dim.width >= this.size.width)
						{
							var h = this.size.width/dim.ratio;
							
							if (h >= this.size.height)
							{
								property = 'width';
								value	 = this.size.width;
							}
						}
						else if(dim.height >= this.size.height)
						{
							var w = this.size.height/dim.ratio;
							
							if (w >= this.size.width)
							{
								property = 'height';
								value	 = this.size.height;
							}
						}
						
						if (property && value)
						{
							i.css(property, value);
						}
						
						
						if (options.image.draggable)
						{
							i.draggable();
						}
						
						i.fadeIn(options.image.fade);
						
						return this;
					},
					empty: function()
					{
						this.content().find('>div>img').parent().remove();
						
						return this;
					},
					open: function()
					{
						/* Show */
						this.element.show();
						
						return this;
					},
					close: function()
					{
						this.element.hide();
						
						return this;	
					},
					blockUI: function()
					{
						if (!this.isUIBlocked)
						{
							this.isUIBlocked = true;
							
							var overlay = $('<div/>').addClass('ui-flow-overlay').css(
							{
								position:			'absolute',
								top:				0,
								left: 				0,
								opacity: 			options.blockUI.opacity,
								width:  			$.boxModel && document.documentElement.clientWidth || document.body.clientWidth,
								height: 			$(document).height(),
								zIndex: 			options.blockUI.zIndex,
								background: 		options.blockUI.background
							}).hide().appendTo('body').fadeIn(options.blockUI.speed);
	
							
							$(window).unbind('resize').bind(
							{
								resize: Core.delegate(this, this.updateUI,[overlay])
							})
							
							overlay.bind(
							{
								click: Core.delegate(this, this.unblockUI)
							})
						}
						return this;
					},
					unblockUI: function()
					{
						this.isUIBlocked = false;
						
						/* Unbind window resize */
						$(window).unbind('resize');
						
						$('body > .ui-flow-overlay').stop(true, true).fadeOut(options.blockUI.speed, function()
						{
							$(this).remove();
						})
						
						this.close();
						
						return this;
					},
					updateUI: function(event, overlay)
					{
						overlay.css(
						{
							width:  $.boxModel && document.documentElement.clientWidth || document.body.clientWidth,
							height: $(document).height()
						});
						
						if(this.timer.resize !== null) 
					    {
					        clearTimeout(this.timer.resize);        
					    }
					    
					    this.timer.resize = setTimeout(Core.delegate(this, this.onResizeStop), options.timeout)
						
						return this;
					},
					updateScroll: function()
					{
					    if(this.timer.scroll !== null) 
					    {
					        clearTimeout(this.timer.scroll);        
					    }
					    
					    this.timer.scroll = setTimeout(Core.delegate(this, this.onScrollStop), options.timeout)
					},
					onScrollStop: function()
					{
						this.element.stop(true, true).animate(
						{
							marginTop:	-this.size.height/2 + $(window).scrollTop()
						})
					},
					onResizeStop: function()
					{
						var size = 
						{
							x: this.size.width  > $(window).width() - options.distance ? $(window).width() - options.distance : this.size.width,
							y: this.size.height > $(window).height() - options.distance ? $(window).height() - options.distance : this.size.height
						}
						
						this.resize(size.x, size.y, function()
						{
							
						});
					},
					preload: function(images, fn)
					{		
						/* Start image preloading */
						Core.preloader.reset().queue(images).preload(fn);
					},
					disableNext: function()
					{
						this.element.find('.ui-flow-next').hide();
					},
					disablePrev: function()
					{
						this.element.find('.ui-flow-prev').hide();
					},
					enableNext: function()
					{
						this.element.find('.ui-flow-next').show();
					},
					enablePrev: function()
					{
						this.element.find('.ui-flow-prev').show();
					}
				}
			});

			if (!this.flow)
			{	
				this.flow = new F();
				
				var box = $('<div/>').addClass('flow');
				var top = $('<div/>').addClass('top');
				var mid = $('<div/>').addClass('mid');
				var bot = $('<div/>').addClass('bot');
				var tlc = $('<div/>').addClass('tlc'); 
				var trc = $('<div/>').addClass('trc'); 
				var blc = $('<div/>').addClass('blc'); 
				var brc = $('<div/>').addClass('brc');
				
				var wrapper = $('<div/>');
				var content = $('<div/>').css(
				{
					height: options.defaultSize.height
				})
				
				var controls = $('<div/>').addClass('controls').appendTo(content);
				var ribbon   = $('<div/>').addClass('ribbon').appendTo(box);
				
				var fn = 
				{
					next: Core.delegate(this, this.next),
					prev: Core.delegate(this, this.prev)
				}
				
				var prev = $('<a/>').addClass('ui-flow-prev').click(Core.delegate(this, this.prev)), next = $('<a/>').addClass('ui-flow-next').click(Core.delegate(this, this.next));
				
				$(document).unbind('keydown').bind(
				{
					keydown: function(e)
					{
						switch(e.which)
						{
							case 37:
								fn.prev();
								break;
							case 39:
								fn.next();
								break;
						}
					}
				});
				
				$.each(
				[
					prev,
					next,
					$('<a/>').addClass('ui-flow-close').click(Core.delegate(this, this.close))
				], function()
				{
					$(this).appendTo(content);
				})
				
				//prev.oe();
				//next.oe();
				
				/* Append parts */
				$.each([top,mid,bot], function()
				{
					$(this).appendTo(box);
				})
			
				/* Top corner(s) */
				$.each([tlc,trc], function()
				{
					$(this).addClass('corner').appendTo(top);
				})
				
				/* Bottom corner(s) */
				$.each([brc,blc], function()
				{
					$(this).addClass('corner').appendTo(bot);
				})
				
				wrapper.append(content).appendTo(mid);
				
				/* Append box to body */
				box.css(
				{
					width:		 options.defaultSize.width,
					marginTop:	-options.defaultSize.height/2,
					marginLeft: -options.defaultSize.width/2
				}).appendTo('body');
				
				/* Set element */
				this.flow.element = box;			
			}
			
			return this.flow;
		},
		play: function()
		{
			this.getFlow().blockUI().open().preload(this.images, Core.delegate(this, this.open));
		},
		open: function(ui)
		{
			this.ui = ui;
			
			/* Reverse image(s) */
			this.ui.images.reverse();

			this.equal(0);
		},
		close: function()
		{
			this.getFlow().empty().close().unblockUI();
		},
		equal: function(index)
		{
			var image = this.ui.images[index];
			
			this.slide =
			{
				current: image.index,
				next: image.index + 1 > this.ui.images.length - 1  ? false : image.index + 1,
				prev: image.index - 1 < 0 ? false : image.index - 1
			}

			/* Window dependablr size */
			var size = 
			{
				x: image.size.width  > $(window).width() - this.options.distance ? $(window).width() - this.options.distance : image.size.width,
				y: image.size.height > $(window).height() - this.options.distance ? $(window).height() - this.options.distance : image.size.height
			}
			
			this.getFlow().empty().reposition('50%', '50%', function()
			{
				this.resize(size.x, size.y, function()
				{
				
					this.setContent(image.image);
				});
			});
			
			/* Hide controls */
			if (false === this.slide.next)
			{
				this.getFlow().disableNext();
			}
			else 
			{
				this.getFlow().enableNext();
			}
			
			if (false === this.slide.prev)
			{
				this.getFlow().disablePrev();
			}
			else 
			{
				this.getFlow().enablePrev();
			}
		},
		next: function()
		{
			if (false !== this.slide.next)
			{
				this.equal(this.slide.next);
			}
		},
		prev: function()
		{
			if (false !== this.slide.prev)
			{
				this.equal(this.slide.prev);
			}
		},
		get: function(index, element)
		{
			var source = $(element).attr('data-image');
				
			this.images.push(source);
		},
		_create: function()
		{
			this.images = [];
			
			/* Collect images */
			this.element.find('li').each(Core.delegate(this, this.get));
		}
	};
	
	/* Widget Namespace */
	$.creo = $.creo || {};
	
	/* Widget */
	$.widget("creo.flow", Flow);
})(jQuery);